using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Reflection;
using System.Xml;
using System.Xml.Schema;
using OpenComposite.Repository.XSDFormGenerator;

/*
 * An XSD-driven dynamic form creator and XML data editor.
 * Using an Xml Schema Definition (XSD) document, this utility dynamically generates a data entry form to create and edit XML data.
 * 
 * Things to do:
 * 
 * Implement a "Close" menu item (closes both XSD and XML)
 * Look at XmlSchemaSimpleType and derived classes like XmlSchemaSimpleTypeList
 * 
 * Bugs:
 * 
 * A simple type that references a simple type with enumerations doesn't show up as a combo box.  Why?
 * A local element ref'ing a global element type'ing a complex element caused an assertion.  Why?
 * An element type'd as a complex type is causing problems
 * 
 * In the Schema Editor:
 *	1.	Can't remove elements of simple type (simple types that are a children to a complex type)
 *	2.	missing feature: DEL key to remove nodes
 *	3.	Renaming a complex type of a complex type caused the child complex type to have a name, instead of the parent element of complex type
 *	4.	Did min inclusive create a max inclusive node instead?
 *	5.	If a simple type has a global simple type restriction base (instead of a built-in one) it doesn't show up in the global list
 * 
 */

namespace OpenComposite.EII.XSDFormGenerator
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	[ToolboxItem(false)]
	public class XSDFormGenerator : System.Windows.Forms.UserControl
	{

		#region Initialization
		public XSDFormGenerator()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			this.SetStyle(ControlStyles.ResizeRedraw, false);
			this.UpdateStyles();
		}
		public XSDFormGenerator(string XMLSchema, string XMLData, bool isOutputSchema, string XMLFormStyle)
		{
			InitializeComponent();

			_xmlschema = XMLSchema;
			_isOutputSchema = isOutputSchema;
			_XMLData = XMLData;

			StringReader sr = new StringReader(XMLSchema);
			schema = XmlSchema.Read(sr, new ValidationEventHandler(SchemaValidationHandler));
			sr.Close();
			CompileSchema();


			doc = new XmlDataDocument();
			// open the schema again
			sr = new StringReader(XMLSchema);
			// read it into the DataSet member
			doc.DataSet.ReadXmlSchema(sr);
			sr.Close();
			foreach ( DataTable dt in doc.DataSet.Tables ) {
				dt.Namespace = doc.DataSet.Namespace;
				foreach ( DataColumn col in dt.Columns ) {
					col.Namespace = doc.DataSet.Namespace;
				}
			}

			//FormStyle fs = new FormStyle();
			//FormStyle.ItemsRow ir = fs.Items.NewItemsRow();
			if ( XMLFormStyle != null ) {
				sr = new StringReader(XMLFormStyle);
				_formStyle.ReadXml(sr);
				sr.Close();
			}


			ConstructGUI(doc.DataSet);

			if ( !isOutputSchema && XMLData != null )
				this.XML = XMLData;

			this.SetStyle(ControlStyles.ResizeRedraw, false);
			this.UpdateStyles();
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.SuspendLayout();
			// 
			// XSDFormGenerator
			// 
			this.AutoScroll = true;
			this.DoubleBuffered = true;
			this.Name = "XSDFormGenerator";
			this.Size = new System.Drawing.Size(574, 420);
			this.ResumeLayout(false);

		}
		#endregion

		#endregion

		#region Public Members

		#region Properties
		
		public string FormDefinitionXML
		{
			get
			{
				_FDxML = "";

				_formStyle.AcceptChanges();

				StringWriter sw = new StringWriter();
				_formStyle.WriteXml(sw);
				_FDxML = sw.ToString();
				sw.Flush();
				sw.Close();

				return _FDxML;
			}
		}
		public XmlDocument FormDefinition
		{
			get
			{
				XmlDocument xd = new XmlDocument();
				xd.LoadXml(_formStyle.GetXml());
				_FDxML = xd.InnerXml;
				return xd;
			}
		}
        [Browsable(false)]
		public string XML
		{
			get
			{
                if (this.DesignMode)
                    return "";
                try
                {
					this.Focus();
                    _xML = "";

                    doc.DataSet.AcceptChanges();

                    StringWriter sw = new StringWriter();
                    doc.DataSet.WriteXml(sw);
                    _xML = sw.ToString();
                    sw.Flush();
                    sw.Close();

                    XmlDocument xdNew = new XmlDocument();
                    XmlNode nn;

                    try
                    {
						if ( doc.ChildNodes.Count > 0 ) {
							if ( doc.ChildNodes[0].Name == "NewDataSet" )
								nn = xdNew.ImportNode(doc.ChildNodes[0].ChildNodes[0], true);
							else
								nn = xdNew.ImportNode(doc.ChildNodes[0], true);

							xdNew.AppendChild(nn);
						}
                    }
                    catch { }

                    //StringWriter s = new StringWriter();

                    //xdNew.Save(s);
                    //xML = s.ToString();
                    //s.Flush();
                    //s.Close();

                    using (StringWriter swr = new StringWriter())
                    using (XmlTextWriter xw = new XmlTextWriter(swr))
                    {
                        xw.Indentation = 3;
                        xw.IndentChar = ' ';
                        xw.Formatting = Formatting.Indented;
                        xdNew.WriteTo(xw);
                        _xML = swr.ToString();
                    }
                }
                catch
                {
                    _xML = "";
                }
				return _xML;

			}
			set
			{
                if (value != null && value != "" && !this.DesignMode)
                {
                    doc.LoadXml(value);
                    UpdateTableInfo();
                }
			}
		}
		
		#endregion

		#region Methods
		
		public void SetXML(string xml)
		{
			//StringReader sr = new StringReader(xml);
			//doc.Load(xml);
			doc.LoadXml(xml);
			// setup to point to the first record in the root table
			foreach ( DataTable dt in doc.DataSet.Tables ) {
				// but we're only interested in the toplevel tables
				if ( dt.ParentRelations.Count == 0 ) {
					TableInfo ti = tableInfo[dt] as TableInfo;
					ti.pos = 1;
					ti.rows = dt.Rows.Count;
					FirstRecord(dt, ti);
					UpdateRecordCountInfo(dt);
				}
			}
		}
		public string GetXML()
		{
			string retXMLString = "";

			doc.DataSet.AcceptChanges();
			//DialogResult res = saveXmlAsDlg.ShowDialog();
			//if (res == DialogResult.OK)
			//{
			//    xmlFileName = saveXmlAsDlg.FileName;
			//    StreamWriter sw = new StreamWriter(xmlFileName, false, System.Text.Encoding.UTF8);
			//    doc.DataSet.WriteXml(sw);
			//    sw.Flush();
			//    sw.Close();
			//}
			StringWriter sw = new StringWriter();
			doc.DataSet.WriteXml(sw);
			retXMLString = sw.ToString();
			sw.Close();

			return retXMLString;
		}

		public bool InitializeForm(XmlSchema xsd, XmlDocument xdStyle, bool isOutput, XmlDocument xdData)
		{
			bool bSuccess = false;
			try {
				this.Controls.Clear();

				using ( StringWriter sw = new StringWriter() ) {
					xsd.Write(sw);
					_xmlschema = sw.ToString();
				}
				_isOutputSchema = isOutput;
				if ( xdData != null )
					_XMLData = xdData.InnerXml;
				else
					_XMLData = null;

				schema = xsd;

				CompileSchema();

				doc = new XmlDataDocument();
				// open the schema again
				using ( StringReader sr = new StringReader(_xmlschema) ) {
					// read it into the DataSet member
					doc.DataSet.ReadXmlSchema(sr);
				}
				foreach ( DataTable dt in doc.DataSet.Tables ) {
					dt.Namespace = doc.DataSet.Namespace;
					foreach ( DataColumn col in dt.Columns ) {
						col.Namespace = doc.DataSet.Namespace;
					}
				}

				if ( xdStyle != null ) {
					if ( _formStyle == null )
						_formStyle = new FormStyle();
					using ( StringReader sr = new StringReader(xdStyle.InnerXml) ) {
						_formStyle.ReadXml(sr);
					}
				}

				ConstructGUI(doc.DataSet);

				if ( !isOutput && xdData != null )
					this.XML = xdData.InnerXml;

				bSuccess = true;
			} catch ( Exception ex ) {
				bSuccess = false;
				MessageBox.Show(ex.Message, "XSD Form Generator", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
			return bSuccess;
		}
		public bool InitializeForm(string XMLSchema, string XMLData, bool isOutputSchema, string XMLFormStyle)
		{
			bool bSuccess = false;
			try {
				this.Controls.Clear();

				_xmlschema = XMLSchema;
				_isOutputSchema = isOutputSchema;
				_XMLData = XMLData;

				if ( XMLSchema == null || XMLSchema == "" )
					return true;

				using ( StringReader sr = new StringReader(XMLSchema) )
					schema = XmlSchema.Read(sr, new ValidationEventHandler(SchemaValidationHandler));
				
				CompileSchema();

				doc = new XmlDataDocument();
				// open the schema again
				using ( StringReader sr = new StringReader(XMLSchema) ) {
					// read it into the DataSet member
					doc.DataSet.ReadXmlSchema(sr);
				}
				foreach ( DataTable dt in doc.DataSet.Tables ) {
					dt.Namespace = doc.DataSet.Namespace;
					foreach ( DataColumn col in dt.Columns ) {
						col.Namespace = doc.DataSet.Namespace;
					}
				}
				//FormStyle fs = new FormStyle();
				//FormStyle.ItemsRow ir = fs.Items.NewItemsRow();
				if ( XMLFormStyle != null ) {
					using ( StringReader sr = new StringReader(XMLFormStyle) ) {
						_formStyle.ReadXml(sr);
					}
				}

				ConstructGUI(doc.DataSet);

				if ( !isOutputSchema && XMLData != null )
					this.XML = XMLData;

				bSuccess = true;
			} catch ( Exception ex ) {
				bSuccess = false;
				MessageBox.Show(ex.Message, "XSD Form Generator", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
			return bSuccess;
		}

		#endregion

		#endregion

		#region Protected Members

		#region Methods
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose(bool disposing)
		{
			if ( disposing ) {
				//if ( components != null ) {
				//    components.Dispose();
				//}
			}
			base.Dispose(disposing);
		}
		#endregion

		#endregion

		#region Private Members

		#region Variables


		private XmlSchema schema = null;
		private XmlDataDocument doc = null;
		//private string xmlFileName = null;
		private Hashtable tableInfo = new Hashtable();

		private Button _firstCreateButton = null;
		private bool _firstCreateButtonCreated = false;

		//private Label _lblMain = null;

		private string _XMLData = null;
		private string _FDxML = null;
		private string _xML = null;
		private string _xmlschema = null;
		private bool _isOutputSchema;
		private FormStyle _formStyle = new FormStyle();
		private FormStyle.ItemRow _row = null;
		private bool _specialCase = false;
		private bool _firstRecordCreated = false;

		private const int _ColumnWidth = 85;
		private const int _PreColumnWidth = -25;//33;
		private const int _DataGridViewHeigth = 150;
		private System.Drawing.Color _STANDARD_COLOR = System.Drawing.Color.Black;
		private int _STANDARD_COLOR_INT32 = System.Drawing.Color.Black.ToArgb();
		private const string _STANDARD_FONT = "Microsoft Sans Serif";
		private const float _STANDARD_FONT_SIZE = 8.0f;
		//private FontStyle _STANDARD_FONT_STYLE = FontStyle.Bold;
		private string _STANDARD_FONT_STYLE_STRING = FontStyle.Bold.ToString();
        private const string _RECORD_VIEW = "RecordView";
        private const string _DATA_GRID_VIEW = "DataGridView";
		private const string _CANONICAL_XMLNS = "http://www.theopencomposite.com/canonical_document";
		//private IContainer components;

		#endregion

		#region Methods

		private void UpdateTableInfo()
		{
			// setup to point to the first record in the root table
			foreach ( DataTable dt in doc.DataSet.Tables ) {
				// but we're only interested in the toplevel tables
				if ( dt.ParentRelations.Count == 0 ) {
					TableInfo ti = tableInfo[dt] as TableInfo;
					ti.pos = 1;
					ti.rows = dt.Rows.Count;
					FirstRecord(dt, ti);
					UpdateRecordCountInfo(dt);
				}
			}
		}

		#region CompileSchema
		// Compile the schema as it exists in the XmlSchema structure, displaying any
		// errors in the schema error edit box and displaying the schema itself in
		// the schema edit box.
		private void CompileSchema()
		{
			XmlSchemaSet xset = new XmlSchemaSet();
			xset.ValidationEventHandler += new ValidationEventHandler(SchemaValidationHandler);
			xset.Add(schema);
			xset.Compile();
		}
		#endregion

		#region Functions That Inspect The Schema

		private XmlSchemaAttribute GetLocalAttribute(XmlSchemaComplexType ct, string name)
		{
			for ( int i = 0; i < ct.Attributes.Count; i++ ) {
				XmlSchemaAttribute attr = ct.Attributes[i] as XmlSchemaAttribute;
				if ( attr != null ) {
					if ( attr.QualifiedName.Name == name ) {
						return attr;
					}
				}
			}
			return null;
		}

		private XmlSchemaElement GetLocalElement(XmlSchemaComplexType ct, string name)
		{
			XmlSchemaSequence seq = ct.ContentTypeParticle as XmlSchemaSequence;
			if ( seq != null ) {
				for ( int i = 0; i < seq.Items.Count; i++ ) {
					XmlSchemaElement el = seq.Items[i] as XmlSchemaElement;
					if ( el != null ) {
						if ( el.QualifiedName.Name == name ) {
							return el;
						}
					}
				}
			}
			return null;
		}

		private XmlSchemaComplexType GetLocalComplexType(XmlSchemaElement el)
		{
			XmlSchemaComplexType obj = el.SchemaType as XmlSchemaComplexType;
			return obj;
		}

		private XmlSchemaElement GetGlobalElement(string name)
		{
			XmlQualifiedName qname = new XmlQualifiedName(name, schema.TargetNamespace);
			XmlSchemaObject obj = schema.Elements[qname];
			return obj as XmlSchemaElement;
		}

		private XmlSchemaSimpleType GetGlobalSimpleType(string name)
		{
			for ( int i = 0; i < schema.Items.Count; i++ ) {
				XmlSchemaSimpleType obj = schema.Items[i] as XmlSchemaSimpleType;
				if ( obj != null ) {
					if ( obj.Name == name ) {
						return obj;
					}
				}
			}
			return null;
		}

		private XmlSchemaAttribute GetGlobalAttribute(string name)
		{
			XmlSchemaAttribute obj = schema.Attributes[new XmlQualifiedName(name, schema.TargetNamespace)] as XmlSchemaAttribute;
			return obj;
		}

		private XmlSchemaComplexType GetGlobalComplexType(string name)
		{
			for ( int i = 0; i < schema.Items.Count; i++ ) {
				XmlSchemaComplexType obj = schema.Items[i] as XmlSchemaComplexType;
				if ( obj != null ) {
					if ( obj.Name == name ) {
						return obj;
					}
				} else {
					XmlSchemaElement el2 = schema.Items[i] as XmlSchemaElement;
					if ( el2 != null ) {
						if ( el2.SchemaType is XmlSchemaComplexType ) {
							obj = el2.SchemaType as XmlSchemaComplexType;
							if ( ( (XmlSchemaElement)schema.Items[i] ).Name == name ) {
								// *** The returning complex type does not have any associated qualified name!!! ****
								return obj;
							}
						}
					}
				}
			}
			return null;
		}

		private void GetFacetInfo(TypeInfo ti, XmlSchemaSimpleTypeRestriction rs)
		{
			foreach ( XmlSchemaFacet facet in rs.Facets ) {
				// There's probably a better way to do this with reflection or some such
				// process, but this old C++ programmers don't learn new tricks easily.
				switch ( facet.GetType().ToString() ) {
					case "System.Xml.Schema.XmlSchemaLengthFacet": {
							ti.length = facet.Value;
							break;
						}

					case "System.Xml.Schema.XmlSchemaMinLengthFacet": {
							ti.minLength = facet.Value;
							break;
						}

					case "System.Xml.Schema.XmlSchemaMaxLengthFacet": {
							ti.maxLength = facet.Value;
							break;
						}

					case "System.Xml.Schema.XmlSchemaPatternFacet": {
							ti.pattern = facet.Value;
							break;
						}

					case "System.Xml.Schema.XmlSchemaEnumerationFacet": {
							ti.enumeration.Add(facet.Value);
							break;
						}

					case "System.Xml.Schema.XmlSchemaMaxInclusiveFacet": {
							ti.maxInclusive = facet.Value;
							break;
						}

					case "System.Xml.Schema.XmlSchemaMaxExclusiveFacet": {
							ti.maxExclusive = facet.Value;
							break;
						}

					case "System.Xml.Schema.XmlSchemaMinInclusiveFacet": {
							ti.minInclusive = facet.Value;
							break;
						}

					case "System.Xml.Schema.XmlSchemaMinExclusiveFacet": {
							ti.minExclusive = facet.Value;
							break;
						}

					case "System.Xml.Schema.XmlSchemaFractionDigitsFacet": {
							ti.fractionDigits = facet.Value;
							break;
						}

					case "System.Xml.Schema.XmlSchemaTotalDigitsFacet": {
							ti.totalDigits = facet.Value;
							break;
						}

					case "System.Xml.Schema.XmlSchemaWhiteSpaceFacet": {
							ti.whiteSpace = facet.Value;
							break;
						}
				}
			}
		}

		private TypeInfo GetTypeInfo(XmlSchemaComplexType ct, string name)
		{
			TypeInfo ti = null;

			// is it an element?
			XmlSchemaElement el = null;
			el = GetLocalElement(ct, name);

			// *** 5/10/2003 *** Search global element list also
			if ( el == null ) {
				el = GetGlobalElement(name);
			}

			// or is it an attribute?
			XmlSchemaAttribute attr = null;
			if ( ct != null ) {
				attr = GetLocalAttribute(ct, name);
			}

			if ( el != null ) {
				// is it an element of simple type?
				if ( el.SchemaType is XmlSchemaSimpleType ) {
					// (paths have been tested)
					// yes...get the restriction base to find the type
					XmlSchemaSimpleType st = el.SchemaType as XmlSchemaSimpleType;
					XmlSchemaSimpleTypeRestriction rest = st.Content as XmlSchemaSimpleTypeRestriction;
					if ( rest != null ) {
						if ( rest.BaseTypeName.Namespace == "" ) {
							st = GetGlobalSimpleType(rest.BaseTypeName.Name);
							rest = st.Content as XmlSchemaSimpleTypeRestriction;
							string typename = rest.BaseTypeName.Name;
							ti = new TypeInfo(typename);
							GetFacetInfo(ti, rest);
						} else {
							string typename = rest.BaseTypeName.Name;
							ti = new TypeInfo(typename);
							GetFacetInfo(ti, rest);
						}
					}
				} else {
					// no...get the attribute type
					// does it reference a global element?
					if ( el.RefName.Name != "" ) {
						// (path has been tested)
						el = GetGlobalElement(el.RefName.Name);
						if ( el != null ) {
							string typename = el.SchemaTypeName.Name;
							ti = new TypeInfo(typename);
						}
					} else {
						// (path has been tested)
						// no...the type is specified in the element

						// Does this reference a global simple type?
						string typename = el.SchemaTypeName.Name;
						if ( el.SchemaTypeName.Namespace == "" ) {
							XmlSchemaSimpleType st = GetGlobalSimpleType(typename);
							XmlSchemaSimpleTypeRestriction rest = st.Content as XmlSchemaSimpleTypeRestriction;
							if ( rest != null ) {
								typename = rest.BaseTypeName.Name;
								ti = new TypeInfo(typename);
								GetFacetInfo(ti, rest);
							}
						} else {
							ti = new TypeInfo(typename);
						}
					}
				}
			} else
				if ( attr != null ) {
					// does it reference a global attribute?
					if ( attr.RefName.Name != "" ) {
						// yes...get the type of the reference
						// !!! PATH HAS NOT BEEN TESTED !!!
						attr = GetGlobalAttribute(attr.RefName.Name);
						if ( attr != null ) {
							string typename = attr.SchemaTypeName.Name;
							ti = new TypeInfo(typename);
						}
					} else {
						// no...get the type of the attribute
						// is it of simple type defined globally?
						if ( attr.AttributeSchemaType != null && attr.AttributeSchemaType is XmlSchemaSimpleType ) {
							// (path has been tested)
							XmlSchemaSimpleType st = GetGlobalSimpleType(attr.SchemaTypeName.Name);
							if ( st != null ) {
								XmlSchemaSimpleTypeRestriction rest = st.Content as XmlSchemaSimpleTypeRestriction;
								if ( rest != null ) {
									string typename = rest.BaseTypeName.Name;
									ti = new TypeInfo(typename);
									GetFacetInfo(ti, rest);
								}
							}
						} else {
							// (path has been tested)
							string typename = attr.SchemaTypeName.Name;
							ti = new TypeInfo(typename);
						}
					}
				}
			return ti;
		}

		#endregion

		#region Construct GUI

		private void ConstructGUI(DataSet dataSet)
		{
			// clear the GUI
			// not implemented

			GroupBox gbMain = null;
			Label lblMain = null;
			Point pos = new Point(10, 25);
			// get all tables in the dataset
			foreach ( DataTable dt in dataSet.Tables ) {
				// but we're only interested in the toplevel tables
				if ( dt.ParentRelations.Count == 0 ) {
					/*
						* Rule 1:
						* A top level table will be a top level element in the schema that
						* is of a complex type.  The element name will be the table name.
						* What we want to identify is the complex type that the table references,
						* so that we can determine the data types of the columns.
						* 
						* Any other rules???
						*/
					XmlSchemaElement el = GetGlobalElement(dt.TableName);
					if ( el != null ) {
						XmlSchemaComplexType ct;
						// references a global complex type?
						if ( el.SchemaTypeName.Name != "" ) {
							string name = el.RefName.Name != "" ? el.RefName.Name : el.SchemaTypeName.Name;
							ct = GetGlobalComplexType(name);
						}
							// contains a complex type?
						else {
							ct = el.SchemaType as XmlSchemaComplexType;
						}
						if ( ct != null ) {
							Point p2 = ConstructGUI(pos.X, pos.Y, dt, this, ct);
							pos.Y += p2.Y;
						}
					} else {
						XmlSchemaElement elDS = GetGlobalElement(dataSet.DataSetName);
						XmlSchemaComplexType ctDS = elDS.SchemaType as XmlSchemaComplexType;
						if ( ctDS != null ) {
							_specialCase = true;
							XmlSchemaElement elDT = GetLocalElement(ctDS, dt.TableName);
							XmlSchemaComplexType ctDT = elDT.SchemaType as XmlSchemaComplexType;
							if ( gbMain == null ) {
								gbMain = CreateGroupBox(pos.X, pos.Y, doc.DataSet.DataSetName, this, out lblMain);
							}

							if ( ctDT != null ) {
								Point p2 = ConstructGUI(pos.X, pos.Y, dt, gbMain, ctDT);
								pos.Y += p2.Y;
							}
						}
					}
				}
			}
			if ( _isOutputSchema && !_firstRecordCreated ) {
				if ( !_specialCase ) {
					NewRecord(_firstCreateButton, new EventArgs());
					_firstRecordCreated = true;
				} else {
					foreach ( DataTable dt in doc.DataSet.Tables ) {
						if ( dt.ParentRelations.Count == 0 ) {
							NewRecord(dt, new EventArgs());
						}
					}
					_firstRecordCreated = true;
				}
			}
		}
		private Point ConstructGUI(int absx, int absy, DataTable dt, Control gbParent, XmlSchemaComplexType ct)
		{
			// for this data table, construct a groupbox as a container for
			//	record scrollbar
			//	table columns
			//			if (dt.TableName=="TaxaNotes")
			//			{
			//				MessageBox.Show(dt.TableName);
			//			}

			Control gb1;
			//if ( true ) {
				gb1 = new GroupBox();
			//} else {
			//    // TODO: hide groupbox frame
			//    gb1 = new Panel();
			//}

			gb1.Font = new Font(gb1.Font, FontStyle.Bold);
			gb1.ForeColor = _STANDARD_COLOR;
			gb1.Text = dt.TableName;
			gb1.Location = new Point(absx, absy);
			gb1.Parent = gbParent;
			gb1.Visible = true;
			gb1.ContextMenuStrip = CreateContextMenuStrip();
			gb1.Tag = GetGroupBoxTag(gb1);
			gb1.AutoSize = true;

			DataRow[] rows = _formStyle.Item.Select("Name = '" + dt.TableName + "'");
            if (rows != null && rows.Length > 0)
            {
                _row = ((FormStyle.ItemRow)rows[0]);
                ChangeGroupBoxStyle(gb1, _row);
            }
            else
            {
                _row = null;
            }

			tableInfo[dt] = new TableInfo();
			//t
			XmlDocument xd = new XmlDocument();
			xd.LoadXml(_xmlschema);
			XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
			nsmgr.AddNamespace("xs", "http://www.w3.org/2001/XMLSchema");
			//nsmgr.AddNamespace("", _CANONICAL_XMLNS);

			int relx = 10;
			int rely = 20;

			XmlNode nodeMaxOccurs = xd.SelectSingleNode("//xs:element[@name=\"" + dt.ToString() + "\"]/@maxOccurs", nsmgr);
			if ( nodeMaxOccurs != null ) {
				if ( nodeMaxOccurs.Value != "0" && nodeMaxOccurs.Value != "1" )//&& _row != null && _row.Representation != _DATA_GRID_VIEW)
                {
					if ( _row == null ) {
						//CreateRecordNavigationBar(10, 15, gb1, dt, true);
						CreateRecordNavigationBar(10, 15, gb1, dt, false);
						//rely = 40;
					} else
                        if (_row.Representation == _RECORD_VIEW)
                        {
                            CreateRecordNavigationBar(10, 15, gb1, dt, true);
                            rely = 40;
                        }
                        else
                        {
                            CreateRecordNavigationBar(10, 15, gb1, dt, false);
                        }
				}
			} else {
				CreateRecordNavigationBar(10, 15, gb1, dt, false);
			}


			//CreateRecordNavigationBar(10, 15, gb1, dt);

			//int relx = 10;				// and indented by 10 pixels
			//int rely = 40;				// and 30 pixels from top of groupbox

			int rx = 0;					// assume no children
			int choiceIdx = 0;
			int maxOccurs = 1;
			if ( nodeMaxOccurs != null ) {
				if ( nodeMaxOccurs.Value.ToLowerInvariant().Equals("unbounded") )
					maxOccurs = int.MaxValue;
				else if ( !int.TryParse(nodeMaxOccurs.Value, out maxOccurs) )
					maxOccurs = 1;
			}
			if ( ( maxOccurs > 1 && _row == null ) || ( maxOccurs > 1 && _row != null && !_row.IsRepresentationNull() && _row.Representation != _RECORD_VIEW ) )
            {
				Control c = CreateDataGrid(relx, rely, gb1, dt);
				//relx += 0;
				rely += _DataGridViewHeigth;
				//rely += 20;
				//if (c.Size.Width > relx)
				//    relx = c.Size.Width;
			} else
			//if (_row != null && _row.Representation != _DATA_GRID_VIEW)
            {
				// For each column in the table...
				foreach ( DataColumn col in dt.Columns ) {
					// if it's not an internal ID...
					if ( col.ColumnMapping != MappingType.Hidden ) {
						// *** 5/10/2003 *** Check for a simple content type.
						XmlSchemaSimpleContent sc = ct.ContentModel as XmlSchemaSimpleContent;
						if ( sc != null ) {
							CreateLabel(relx, rely, dt.TableName, gb1);
							XmlSchemaSimpleContentExtension sce = sc.Content as XmlSchemaSimpleContentExtension;
							if ( sce != null ) {
								TypeInfo ti = new TypeInfo(sce.BaseTypeName.Name);
								CreateEditControl(relx + 120, rely, ti, gb1, dt, col);
							}
						} else {
							// display its name
							CreateLabel(relx, rely, col.ColumnName, gb1);
							/*
								* INACCESSIBLE INFORMATION THAT WOULD HAVE BEEN REALLY USEFUL!!!
								* col.XmlDataType is the data type, simple or global
								* col.SimpleType contains the facets and XmlBaseType of the simple type
								* These properties are INTERNAL classes!  Since we have to get this
								* information ourselves...
								*/
							TypeInfo ti = GetTypeInfo(ct, col.ColumnName);
							if ( ti != null ) {
								/*Control editCtrl=*/
								CreateEditControl(relx + 120, rely, ti, gb1, dt, col);
							}
						}
					}
					#region HiddenColums
					//if ( col.ColumnMapping == MappingType.Hidden ) {
						//// *** columns that define relationships do not need to be displayed ***

						//Label lbl=CreateLabel(relx, rely, col.ColumnName, gb1);
						//Control editCtrl=CreateEditControl(relx+120, rely, new TypeInfo("string"), gb1, dt, col);
						//editCtrl.Size=new Size(50, 20);
						//((TextBox)editCtrl).ReadOnly=true;

						//// These are columns that are created when the schema is loaded into a dataset.
						//// They are not part of the schema itself, but an artifact of the "tablization"
						//// of the schema.

						//// identify child relations
						//// Does this column have a relationship with a child table?
						//// data relations are always 1:1
						//if (dt.ChildRelations.Count != 0)
						//{
						//    DataRelation dr=dt.ChildRelations[0];
						//    for (int i=0; i<dr.ChildColumns.Length; i++)
						//    {
						//        if (dr.ChildColumns[i].ColumnName==col.ColumnName)
						//        {
						//            lbl.ForeColor=Color.Blue;
						//            break;
						//        }
						//    }
						//}

						//// identify parent relations.
						//// Does this column have a relationship with a parent table?
						//// data relations are always 1:1
						//if (dt.ParentRelations.Count != 0)
						//{
						//    DataRelation dr=dt.ParentRelations[0];
						//    for (int i=0; i<dr.ParentColumns.Length; i++)
						//    {
						//        if (dr.ParentColumns[i].ColumnName==col.ColumnName)
						//        {
						//            lbl.ForeColor=Color.Red;
						//            break;
						//        }
						//    }
						//}
					//}
					#endregion
					//rely += 20;
					if ( col.ColumnMapping != MappingType.Hidden )
						rely += 20;
				}
			}
			//else
			//{
			//    if (nodeMaxOccurs!= null && _row != null && !_row.IsRepresentationNull() && _row.Representation == _DATA_GRID_VIEW)
			//    {
			//        Control c = CreateDataGrid(relx, rely, gb1, dt);
			//        //relx += 0;
			//        rely += _DataGridViewHeigth;
			//        //rely += 20;
			//        //if (c.Size.Width > relx)
			//        //    relx = c.Size.Width;
			//    }
			//}



			//int rx=0;					// assume no children
			//int choiceIdx=0;          // letzten 2 zwei Codezeilen nach oben verlegt
			// Get child relationships, which are displayed as indented groupboxes
			foreach ( DataRelation childRelation in dt.ChildRelations ) {
				DataTable dt2 = childRelation.ChildTable;

				/* Rule 1: The data table references a global complex type.
					* The table name is the element name of complex type in the
					* current complex type object collection.  As with the root
					* table, we need to find the element, get the type, then get
					* the complex type.
					* 
					* Rule 2: If this isn't a global complex type (ct2==null), then
					* the element is a local complex type!
					*/
				XmlSchemaElement el2 = null;
				XmlSchemaElement el3 = null;
				XmlSchemaComplexType ct2 = null;

				//				if (dt2.TableName=="Author")
				//				{
				//					MessageBox.Show("Searching: "+dt2.TableName);
				//				}

				// *** 5/10/2003 *** Handle complex types with "choice" schemas.
				// A "choice" is represented as separate tables, each indexing the same choice list,
				// and the child relation index tracks the choice items!
				XmlSchemaChoice choice = ct.ContentTypeParticle as XmlSchemaChoice;
				if ( choice != null ) {
					//for (int i=0; i<choice.Items.Count; i++)
					{
						XmlSchemaElement elChoice = choice.Items[choiceIdx] as XmlSchemaElement;
						if ( elChoice != null ) {
							ct2 = GetGlobalComplexType(elChoice.RefName.Name);
							Point p = ConstructGUI(relx + 20, rely + 20, dt2, gb1, ct2);
							if ( p.X > rx ) {
								rx = p.X;				// indent level
							}
							rely += p.Y + 20;			// vertical spacing between child tables
							//							break;
						}
					}
					++choiceIdx;
					continue;
				} else if ( ct != null ) {
					// get the local element associated with the table name in this complex type
					el2 = GetLocalElement(ct, dt2.TableName);

					// if it exists...
					if ( el2 != null ) {
						// get either the refname or the schema type name
						string name = el2.RefName.Name != "" ? el2.RefName.Name : el2.SchemaTypeName.Name;

						// find the complex type defining the element type.
						ct2 = GetGlobalComplexType(name);
						if ( ct2 == null ) {
							// if the complex type is not defined globally, then check if it's defnied locally
							ct2 = GetLocalComplexType(el2);

							// if it's not defined locally, check if the element is referring to a global ELEMENT
							if ( ct2 == null ) {
								el3 = GetGlobalElement(name);
							}
						}
					}
				} else {
					el3 = GetGlobalElement(dt2.TableName);
				}

				if ( ct2 != null ) {

					Point p = ConstructGUI(relx + 20, rely, dt2, gb1, ct2);
					if ( p.X > rx ) {
						rx = p.X;				// indent level
					}
					rely += p.Y + 20;			// vertical spacing between child tables
				}

				// *** 5/10/2003 *** This handles the case where a local element references a global element!
					// This structure must be created as a child node, complete with groupbox support.
				else if ( el3 != null ) {
					// *** 5/12/2003 *** Create a tableInfo entry.
					// NOTE THAT A SEPARATE GROUPBOX WITH RECORD NAVIGATION IS NOT CREATED!
					tableInfo[dt2] = new TableInfo();
					string name = el3.SchemaTypeName.Name;
					TypeInfo ti = new TypeInfo(name);
					CreateLabel(relx, rely, dt2.TableName, gb1);
					CreateEditControl(relx + 120, rely, ti, gb1, dt2, dt2.Columns[0]);
					rely += 20;			// vertical spacing between rows
				} else {
					//MessageBox.Show("Not found: " + dt.TableName + "." + dt2.TableName);
				}
			}

			// set our size based on number of child tables (indents)
			//gb1.Size=new Size(300+rx, rely+10);
			rows = _formStyle.Item.Select("Name = '" + dt.TableName + "'");
            if (rows != null && rows.Length > 0)
            {
                _row = ((FormStyle.ItemRow)rows[0]);
            }
            else
            {
                _row = null;
            }

			Point ptRet;
			if ( nodeMaxOccurs != null && _row != null && _row.Representation == _DATA_GRID_VIEW ) {
				gb1.Size = new Size(25 + rx + _PreColumnWidth + dt.Columns.Count * _ColumnWidth, rely + 10);
				//return new Point(40 + rx + _PreColumnWidth + dt.Columns.Count * _ColumnWidth, rely + 10);
				ptRet = new Point(gb1.Left + 40, gb1.Height);
				if ( _row != null && !_row.IsLabelNull() && _row.Label &&
					!_row.IsTextVisibleNull() && _row.TextVisible ) {
					Label lblTitle = CreateLabel(absx, absy, _row, gbParent, gb1);
					gb1.Top += lblTitle.Height - 2;
					ptRet.Y += lblTitle.Height;
				}

				//return new Point((dt.Columns.Count - 3) * _ColumnWidth, rely + 30);
			} else {
				gb1.Size = new Size(300 + rx, rely + 10);
				ptRet = new Point(gb1.Left + 40, gb1.Height);
				if ( _row != null && !_row.IsLabelNull() && _row.Label &&
					!_row.IsTextVisibleNull() && _row.TextVisible ) {
					Label lblTitle = CreateLabel(absx, absy, _row, gbParent, gb1);
					gb1.Top += lblTitle.Height - 2;
					ptRet.Y += lblTitle.Height;
				}

				//return new Point(40 + rx, rely + 30);
			}
			return ptRet;
			// return the size of this groupbox, which includes all columns and child tables
			//return new Point(40+rx, rely+10);
			//return new Point(gb1.Size.Width , gb1.Size.Height);

		}

		private ContextMenuStrip CreateContextMenuStrip()
		{
			ToolStripMenuItem toolStripMenuItem1 = new ToolStripMenuItem();

			toolStripMenuItem1.Name = "toolStripMenuItem1";
			toolStripMenuItem1.Size = new System.Drawing.Size(103, 22);
			toolStripMenuItem1.Text = "Edit Form";
			toolStripMenuItem1.Click += new EventHandler(toolStripMenuItem1_Click);

			ContextMenuStrip coMeS = new ContextMenuStrip();

			coMeS.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { toolStripMenuItem1 });
			coMeS.Name = "coMeS";
			coMeS.Size = new System.Drawing.Size(104, 26);

			return coMeS;

		}
		private object GetGroupBoxTag(Control gb)
		{
			if ( gb.Tag != null )
				return gb.Tag;

			string fqn = null;

			if ( ( gb.Parent is GroupBox || gb.Parent is Panel ) && gb.Parent.Tag is string[] ) {
				fqn = ( gb.Parent.Tag as string[] )[1];
			}
			fqn += "/" + gb.Text;

			return new string[] { gb.Text, fqn };
		}

		private GroupBox CreateGroupBox(int x, int y, string name, Control parent, out Label label)
		{
			label = null;

			GroupBox gb1 = new GroupBox();
			gb1.Font = new Font(gb1.Font, FontStyle.Bold);
			gb1.Text = name;
			gb1.Location = new Point(x, y);
			gb1.Parent = parent;
			gb1.Visible = true;
			gb1.AutoSize = true;
			gb1.ContextMenuStrip = CreateContextMenuStrip();

			gb1.Tag = GetGroupBoxTag(gb1);

			DataRow[] rows = _formStyle.Item.Select("Name = '" + name + "'");
			if ( rows != null && rows.Length > 0 ) {
				FormStyle.ItemRow row = ( (FormStyle.ItemRow)rows[0] );
				ChangeGroupBoxStyle(gb1, row);
				if ( row != null && !row.IsLabelNull() && row.Label ) {
					label = CreateLabel(x, y, row, parent, gb1);
					gb1.Location = new Point(gb1.Location.X, gb1.Location.Y + label.Height);
					//_lblMain = label;
					//_lblMain.Location = new Point(1, 1);
				}
			}

			return gb1;
		}
		private void ChangeGroupBoxStyle(Control gb, FormStyle.ItemRow row)
		{
			if ( row != null ) {
				if ( !row.IsTextNull() ) //&& row.Text != "")
					gb.Text = row.Text;

				if ( !row.IsTextVisibleNull() && !row.TextVisible )
					gb.Text = "";

				if ( !row.IsLabelNull() && row.Label )
					gb.Text = "";

				//if (!row.IsColorNull())
				//    gb.ForeColor = System.Drawing.Color.FromArgb(row.Color);

				if ( !row.IsFontNull() && !row.IsFontSizeNull() && !row.IsFontStyleNull() ) {
					switch ( row.FontStyle ) {
						case "Regular":
							gb.Font = new System.Drawing.Font(row.Font, (float)row.FontSize, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ( (byte)( 0 ) ));
							break;
						case "Italic":
							gb.Font = new System.Drawing.Font(row.Font, (float)row.FontSize, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ( (byte)( 0 ) ));
							break;
						case "Bold":
							gb.Font = new System.Drawing.Font(row.Font, (float)row.FontSize, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ( (byte)( 0 ) ));
							break;
						case "Bold Italic":
							gb.Font = new System.Drawing.Font(row.Font, (float)row.FontSize, ( (System.Drawing.FontStyle)( ( System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic ) ) ), System.Drawing.GraphicsUnit.Point, ( (byte)( 0 ) ));
							break;
						default:
							gb.Font = new Font(gb.Font, FontStyle.Bold);
							break;
					}
				}
				if ( !row.IsColorNull() )
					gb.ForeColor = System.Drawing.Color.FromArgb(row.Color);
			}
		}

		#endregion
		
		private Control CreateDataGrid(int x, int y, Control parent, DataTable tag)
		{
			Control ctrl = null;
			DataGridView dgv = new DataGridView();
			parent.SuspendLayout();
			( (System.ComponentModel.ISupportInitialize)( dgv ) ).BeginInit();

			dgv.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
			dgv.Location = new System.Drawing.Point(x, y);
			dgv.Name = "dataGridView1";
			dgv.Parent = parent;
			dgv.Size = new System.Drawing.Size(tag.Columns.Count * _ColumnWidth + _PreColumnWidth, _DataGridViewHeigth);
			dgv.TabIndex = 0;
			dgv.Visible = true;
			dgv.DataSource = tag;
			dgv.AutoSize = true;

			for ( int i = 0; i < dgv.ColumnCount; ++i )
				dgv.Columns[i].Width = _ColumnWidth;

			dgv.Font = new Font(_STANDARD_FONT, _STANDARD_FONT_SIZE, FontStyle.Regular);
			dgv.ForeColor = _STANDARD_COLOR;

			dgv.DataError += new DataGridViewDataErrorEventHandler(dgv_DataError);
			tag.TableNewRow += new DataTableNewRowEventHandler(tag_TableNewRow);

			( (System.ComponentModel.ISupportInitialize)( dgv ) ).EndInit();
			parent.ResumeLayout(false);
			parent.PerformLayout();
			ctrl = dgv;
			return ctrl;
		}
		private Label CreateLabel(int x, int y, FormStyle.ItemRow row, Control parent, Control brother)
		{
			Label lbl = new Label();
			lbl.Location = new Point(x, y);//y + 2);
			lbl.Size = new Size(brother.Size.Width, 15);//30);
			//lbl.BackColor = System.Drawing.Color.DarkGreen;
			lbl.Visible = true;
			lbl.Parent = parent;
			lbl.Font = new Font(_STANDARD_FONT, _STANDARD_FONT_SIZE, FontStyle.Regular);
			lbl.ForeColor = _STANDARD_COLOR;


			if ( row != null ) {
				if ( !row.IsTextNull() )
					lbl.Text = row.Text;

				if ( !row.IsTextVisibleNull() && !row.TextVisible )
					lbl.Text = "";

				if ( !row.IsLabelNull() && !row.Label )
					lbl.Text = "";

				if ( !row.IsColorNull() )
					lbl.ForeColor = System.Drawing.Color.FromArgb(row.Color);

				if ( !row.IsFontNull() && !row.IsFontSizeNull() && !row.IsFontStyleNull() ) {
					switch ( row.FontStyle ) {
						case "Regular":
							lbl.Font = new System.Drawing.Font(row.Font, (float)row.FontSize, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ( (byte)( 0 ) ));
							break;
						case "Italic":
							lbl.Font = new System.Drawing.Font(row.Font, (float)row.FontSize, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ( (byte)( 0 ) ));
							break;
						case "Bold":
							lbl.Font = new System.Drawing.Font(row.Font, (float)row.FontSize, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ( (byte)( 0 ) ));
							break;
						case "Bold Italic":
							lbl.Font = new System.Drawing.Font(row.Font, (float)row.FontSize, ( (System.Drawing.FontStyle)( ( System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic ) ) ), System.Drawing.GraphicsUnit.Point, ( (byte)( 0 ) ));
							break;
						default:
							lbl.Font = new Font(lbl.Font, FontStyle.Bold);
							break;
					}
					lbl.Height = (int)lbl.Font.GetHeight();
					lbl.Height += (int)( lbl.Height * 0.5 );
				}

				if ( !row.IsLabelPositionNull() ) {
					switch ( row.LabelPosition ) {
						case "TopLeft":
							lbl.TextAlign = ContentAlignment.TopLeft;
							break;
						case "TopCenter":
							lbl.TextAlign = ContentAlignment.TopCenter;
							break;
						case "TopRight":
							lbl.TextAlign = ContentAlignment.TopRight;
							break;

						case "MiddleLeft":
							lbl.TextAlign = ContentAlignment.MiddleLeft;
							break;
						case "MiddleCenter":
							lbl.TextAlign = ContentAlignment.MiddleCenter;
							break;
						case "MiddleRight":
							lbl.TextAlign = ContentAlignment.MiddleRight;
							break;

						case "BottomLeft":
							lbl.TextAlign = ContentAlignment.BottomLeft;
							break;
						case "BottomCenter":
							lbl.TextAlign = ContentAlignment.BottomCenter;
							break;
						case "BottomRight":
							lbl.TextAlign = ContentAlignment.BottomRight;
							break;
						default:
							lbl.TextAlign = ContentAlignment.TopLeft;
							break;
					}
				}


			}
			return lbl;
		}
		private Label CreateLabel(int x, int y, string name, Control parent)
		{
			Label lbl = new Label();
			lbl.Location = new Point(x, y + 2);
			lbl.Size = new Size(120, 15);
			lbl.Text = name;
			lbl.Font = new Font(_STANDARD_FONT, _STANDARD_FONT_SIZE, FontStyle.Regular);
			lbl.ForeColor = _STANDARD_COLOR;
			//lbl.Font=new Font(lbl.Font, FontStyle.Regular);
			lbl.Visible = true;
			lbl.Parent = parent;
			return lbl;
		}

		private Control CreateRecordNavigationBar(int x, int y, Control parent, DataTable tag, bool visible)
		{
			Panel navPanel = new Panel();
			navPanel.Location = new Point(x, y);
			navPanel.Size = new Size(280, 19);
			//navPanel.Font = new Font(_STANDARD_FONT, _STANDARD_FONT_SIZE, FontStyle.Regular);
			navPanel.ForeColor = _STANDARD_COLOR;


			if ( visible )
				navPanel.Visible = true;
			else
				navPanel.Visible = false;

			navPanel.Parent = parent;
			navPanel.BorderStyle = BorderStyle.FixedSingle;

			CreateNavButton("<<", 0, 0, new EventHandler(FirstRecord), navPanel, tag);
			CreateNavButton("<", 30, 0, new EventHandler(PrevRecord), navPanel, tag);
			CreateNavButton("*", 60, 0, new EventHandler(NewRecord), navPanel, tag);
			CreateNavButton(">", 90, 0, new EventHandler(NextRecord), navPanel, tag);
			CreateNavButton(">>", 120, 0, new EventHandler(LastRecord), navPanel, tag);

			TextBox tb = new TextBox();
			tb.Location = new Point(150, 2);
			tb.Size = new Size(100, 18);
			tb.BorderStyle = BorderStyle.None;
			tb.Font = new Font("Tahoma", 8, FontStyle.Regular);
			tb.Parent = navPanel;
			tb.Visible = true;
			tb.Text = "   record 0 of 0";
			( (TableInfo)tableInfo[tag] ).tb = tb;

			CreateNavButton("X", 250, 0, new EventHandler(DeleteRecord), navPanel, tag);

			UpdateRecordCountInfo(tag);

			return navPanel;
		}
		private void CreateNavButton(string text, int x, int y, EventHandler ev, Control parent, object tag)
		{
			Button btnNewRecord = new Button();
			btnNewRecord.Text = text;
			btnNewRecord.Location = new Point(x, y);
			btnNewRecord.Size = new Size(30, 17);
			btnNewRecord.Parent = parent;
			btnNewRecord.Visible = true;
			btnNewRecord.Font = new Font("Tahoma", 8, FontStyle.Bold);
			btnNewRecord.Tag = tag;
			btnNewRecord.Click += ev;

			if ( btnNewRecord.Text == "*" && !_firstCreateButtonCreated ) {
				_firstCreateButton = btnNewRecord;
				_firstCreateButtonCreated = true;
			}
		}
		private Control CreateEditControl(int x, int y, TypeInfo ti, Control parent, DataTable dt, DataColumn dc)
		{
			Control ctrl = null;

			// if the schema has an enumeration, then display as a combo box
			if ( ti.enumeration.Count != 0 ) {
				ComboBox cb = new ComboBox();
				cb.Location = new Point(x, y);
				cb.Size = new Size(140, 200);
				cb.Font = new Font(cb.Font, FontStyle.Regular);
				cb.Visible = true;
				cb.Parent = parent;
				foreach ( object obj in ti.enumeration ) {
					cb.Items.Add(obj);
				}
				ctrl = cb;
				ctrl.DataBindings.Add("Text", dt, dc.ColumnName);
			}
				// if the schema has a min/max inclusive set, then display as an up-down control
			else if ( ( ti.minInclusive != null ) && ( ti.maxInclusive != null ) ) {
				NumericUpDown nud = new NumericUpDown();
				nud.Location = new Point(x, y);
				nud.Size = new Size(80, 20);
				nud.Font = new Font(nud.Font, FontStyle.Regular);
				nud.Visible = true;
				nud.Parent = parent;

				nud.Minimum = Convert.ToInt32(ti.minInclusive);
				nud.Maximum = Convert.ToInt32(ti.maxInclusive);
				ctrl = nud;
				ctrl.DataBindings.Add("Text", dt, dc.ColumnName);
			} else {
				// use MaxLength
				// use Tag???
				// NumericUpDown???
				switch ( ti.typeName ) {
					case "boolean": {
							// boolean is implemented as a checkbox
							CheckBox ck1 = new CheckBox();
							ck1.Location = new Point(x, y);
							ck1.Size = new Size(140, 20);
							ck1.Font = new Font(ck1.Font, FontStyle.Regular);
							ck1.Visible = true;
							ck1.Text = "";
							ck1.Parent = parent;
							ck1.AutoCheck = true;
							ctrl = ck1;

							Binding b = new Binding("Checked", dt, dc.ColumnName);
							b.Format += new ConvertEventHandler(TrueFalseToBool);
							ctrl.DataBindings.Add(b);
							break;
						}

					case "string": {
							// textbox
							TextBox tb = new TextBox();
							tb.Location = new Point(x, y);
							tb.Size = new Size(140, 20);
							tb.Font = new Font(tb.Font, FontStyle.Regular);
							tb.Visible = true;
							tb.Parent = parent;
							ctrl = tb;
							ctrl.DataBindings.Add("Text", dt, dc.ColumnName);
							break;
						}

					case "decimal": {
							// right justified
							TextBox tb = new TextBox();
							tb.Location = new Point(x, y);
							tb.Size = new Size(140, 20);
							tb.Font = new Font(tb.Font, FontStyle.Regular);
							tb.Visible = true;
							tb.Parent = parent;
							tb.TextAlign = HorizontalAlignment.Right;
							ctrl = tb;
							ctrl.DataBindings.Add("Text", dt, dc.ColumnName);
							break;
						}

					case "positiveInteger": {
							// right justified
							TextBox tb = new TextBox();
							tb.Location = new Point(x, y);
							tb.Size = new Size(140, 20);
							tb.Font = new Font(tb.Font, FontStyle.Regular);
							tb.Visible = true;
							tb.Parent = parent;
							tb.TextAlign = HorizontalAlignment.Right;
							ctrl = tb;
							ctrl.DataBindings.Add("Text", dt, dc.ColumnName);
							break;
						}

					default: {
							// use a text box for the default data type
							TextBox tb = new TextBox();
							tb.Location = new Point(x, y);
							tb.Size = new Size(140, 20);
							tb.Font = new Font(tb.Font, FontStyle.Regular);
							tb.Visible = true;
							tb.Parent = parent;
							ctrl = tb;
							ctrl.DataBindings.Add("Text", dt, dc.ColumnName);
							break;
						}
				}
			}
			return ctrl;
		}

		private void UpdateRecordCountInfo(DataTable dt)
		{
			// update the text box to reflect the record #
			TableInfo ti = tableInfo[dt] as TableInfo;
			if ( dt.ParentRelations.Count == 0 ) {
				ti.pos = BindingContext[dt].Position + 1;
			}
			// *** 5/12/2003 *** If a child element references a global element, no navigational record is created.  Is this
			// a problem?
			if ( ti.tb != null ) {
				if ( ti.pos > ti.rows )
					ti.pos = ti.rows;

				ti.tb.Text = "   record " + ti.pos.ToString() + " of " + ti.rows.ToString();
			}
		}

		private int GetMatchingRows(DataTable dt)
		{
			TableInfo ti = tableInfo[dt] as TableInfo;
			// get parent relationship
			DataRelation parentRelation = dt.ParentRelations[0];
			// get the parent table
			DataTable dt2 = parentRelation.ParentTable;
			// get the parent column (1:1 relationship always)
			DataColumn dcParent = parentRelation.ParentColumns[0];
			// get the current record # of the parent
			int n = BindingContext[dt2].Position;
			if ( n != -1 ) {
				// get the ID
				string val = dt2.Rows[n][dcParent].ToString();
				// search the child for all records where child.parentID=parent.ID
				string expr = dcParent.ColumnName + "=" + val;
				// save the rows, as we'll use them later on when navigating the child
				ti.dataRows = dt.Select(expr);
			}
			// return the length
			if ( ti.dataRows == null ) {
				return 0;
			}
			return ti.dataRows.Length;
		}
        static internal bool MultiRepresentation(string xmlDocument, string ElementName)
        {
            bool bRet = false;

            XmlDocument xd = new XmlDocument();
            xd.LoadXml(xmlDocument);
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
            nsmgr.AddNamespace("xs", "http://www.w3.org/2001/XMLSchema");
            nsmgr.AddNamespace("", _CANONICAL_XMLNS);

            XmlNode nodeMaxOccurs = xd.SelectSingleNode("//xs:element[@name=\"" + ElementName + "\"]/@maxOccurs", nsmgr);
            if (nodeMaxOccurs != null && nodeMaxOccurs.Value != "0" && nodeMaxOccurs.Value != "1")
                bRet = true;

            return bRet;
        }

		private FormStyle.ItemRow CreateItemRow(GroupBox gb)
		{
            ////bool MultiRepresentation = false;
            //XmlDocument xd = new XmlDocument();
            //xd.LoadXml(_xmlschema);
            //XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
            //nsmgr.AddNamespace("xs", "http://www.w3.org/2001/XMLSchema");
            //nsmgr.AddNamespace("", _CANONICAL_XMLNS);

            //XmlNode nodeMaxOccurs = xd.SelectSingleNode("//xs:element[@name=\"" + ( gb.Tag as string[] )[0] + "\"]/@maxOccurs", nsmgr);
            //if ( nodeMaxOccurs != null && nodeMaxOccurs.Value != "0" && nodeMaxOccurs.Value != "1" )
            //    MultiRepresentation = true;

			FormStyle.ItemRow row = _formStyle.Item.NewItemRow();

			row.Name = ( gb.Tag as string[] )[0];
			row.FQN = ( gb.Tag as string[] )[1];
			row.Type = "complexType";
			row.Text = row.Name;
			row.TextVisible = true;
			row.MultiRepresentation = MultiRepresentation(_xmlschema, (gb.Tag as string[])[0]);            
            row.Representation = "DataGridView";
			row.Label = false;
			row.LabelPosition = "MiddleLeft";
			row.Color = _STANDARD_COLOR_INT32;
			row.Font = _STANDARD_FONT;
			row.FontSize = _STANDARD_FONT_SIZE;
			row.FontStyle = _STANDARD_FONT_STYLE_STRING;

			_formStyle.Item.AddItemRow(row);

			return row;
		}
		#endregion

		#region Event Handlers

		#region Menu And Button Events
		#region Open XSD
		private void mnuOpenXSD_Click(object sender, System.EventArgs e)
		{
			//dlgOpen.DefaultExt = "xsd";
			//dlgOpen.CheckFileExists = true;
			//dlgOpen.Filter = "XSD Files (*.xsd)|*.xsd|All Files (*.*)|*.*";
			//DialogResult res = dlgOpen.ShowDialog();
			//if ( res == DialogResult.OK ) {
			//    //				try
			//    {
			//        // get a stream reader for the XSD file
			//        StreamReader tr = new StreamReader(dlgOpen.FileName);
			//        // read the file into the XmlSchema object
			//        schema = XmlSchema.Read(tr, new ValidationEventHandler(SchemaValidationHandler));
			//        tr.Close();
			//        // report any problems with the schema by compiling it
			//        CompileSchema();
			//        // create the document
			//        doc = new XmlDataDocument();
			//        // open the schema again
			//        tr = new StreamReader(dlgOpen.FileName);
			//        // read it into the DataSet member
			//        doc.DataSet.ReadXmlSchema(tr);
			//        tr.Close();

			//        ConstructGUI(doc.DataSet);
			//    }
			//    //				catch(Exception err)
			//    //				{
			//    //					MessageBox.Show(err.ToString(), "Error processing XSD schema:");
			//    //					schema=null;
			//    //					doc=null;
			//    //				}
			//}
		}
		#endregion

		#region Infer XSD
		private void mnuInferXSD_Click(object sender, System.EventArgs e)
		{
			//dlgOpen.DefaultExt = "xml";
			//dlgOpen.CheckFileExists = true;
			//dlgOpen.Filter = "XML Files (*.xml)|*.xml|All Files (*.*)|*.*";
			//DialogResult res = dlgOpen.ShowDialog();
			//if ( res == DialogResult.OK ) {
			//    try {
			//        // read into XmlSchema because we want the information in that format
			//        doc = new XmlDataDocument();
			//        StreamReader tr = new StreamReader(dlgOpen.FileName);
			//        doc.DataSet.InferXmlSchema(tr, null);
			//        tr.Close();
			//        string strSchema = doc.DataSet.GetXmlSchema();

			//        StreamWriter sw = new StreamWriter("temp.txt", false, System.Text.Encoding.UTF8);
			//        sw.Write(strSchema);
			//        sw.Flush();
			//        sw.Close();

			//        StringReader sr = new StringReader(strSchema);
			//        schema = XmlSchema.Read(sr, new ValidationEventHandler(SchemaValidationHandler));
			//        sr.Close();
			//        CompileSchema();
			//        ConstructGUI(doc.DataSet);
			//    } catch ( Exception err ) {
			//        MessageBox.Show(err.ToString(), "Error inferring schema:");
			//        schema = null;
			//        doc = null;
			//    }
			//}
		}
		#endregion

		#region Open XML
		private void mnuOpenXML_Click(object sender, System.EventArgs e)
		{
			//if ( schema == null ) {
			//    MessageBox.Show("Please load an XSD first.", "Cannot load XML");
			//    return;
			//}
			//dlgOpen.DefaultExt = "xml";
			//dlgOpen.CheckFileExists = true;
			//dlgOpen.Filter = "XML Files (*.xml)|*.xml|All Files (*.*)|*.*";
			//DialogResult res = dlgOpen.ShowDialog();
			//if ( res == DialogResult.OK ) {
			//    xmlFileName = dlgOpen.FileName;
			//    //				try
			//    {
			//        XmlTextReader tr = new XmlTextReader(dlgOpen.FileName);
			//        doc.Load(tr);
			//        tr.Close();

			//        // setup to point to the first record in the root table
			//        foreach ( DataTable dt in doc.DataSet.Tables ) {
			//            // but we're only interested in the toplevel tables
			//            if ( dt.ParentRelations.Count == 0 ) {
			//                TableInfo ti = tableInfo[dt] as TableInfo;
			//                ti.pos = 1;
			//                ti.rows = dt.Rows.Count;
			//                FirstRecord(dt, ti);
			//                UpdateRecordCountInfo(dt);
			//            }
			//        }
			//    }
			//    //				catch(Exception err)
			//    //				{
			//    //					MessageBox.Show(err.ToString(), "Error processing XML document:");
			//    //				}
			//}
		}
		#endregion

		#region Save XML

		private void mnuSaveXML_Click(object sender, System.EventArgs e)
		{
			//if ( doc.DataSet == null ) {
			//    MessageBox.Show("No XML data to save.");
			//    return;
			//}

			//if ( xmlFileName != null ) {
			//    doc.DataSet.AcceptChanges();
			//    StreamWriter sw = new StreamWriter(xmlFileName, false, System.Text.Encoding.UTF8);
			//    doc.DataSet.WriteXml(sw);
			//    sw.Flush();
			//    sw.Close();
			//} else {
			//    mnuSaveXmlAs_Click(sender, e);
			//}
		}

		private void mnuSaveXmlAs_Click(object sender, System.EventArgs e)
		{
			//if ( doc.DataSet == null ) {
			//    MessageBox.Show("No XML data to save.");
			//    return;
			//}

			//doc.DataSet.AcceptChanges();
			//DialogResult res = saveXmlAsDlg.ShowDialog();
			//if ( res == DialogResult.OK ) {
			//    xmlFileName = saveXmlAsDlg.FileName;
			//    //StreamWriter sw=new StreamWriter(xmlFileName, false, System.Text.Encoding.UTF8);
			//    StreamWriter sw = new StreamWriter(xmlFileName, false);
			//    sw.Write(this.XML);
			//    //doc.DataSet.WriteXml(sw);
			//    sw.Flush();

			//    sw.Close();
			//}
		}

		#endregion

		#region Exit Program
		//private void mnuExit_Click(object sender, System.EventArgs e)
		//{
		//    Close();		// signal form to close
		//}
		#endregion

		#region XPath Query
		private void btnXpathQuery_Click(object sender, System.EventArgs e)
		{
			//if ( doc == null ) {
			//    MessageBox.Show("Please load a schema and XML data set first.");
			//    return;
			//}

			//XmlNodeList nodeList = null;
			//try {
			//    nodeList = doc.SelectNodes(edXPath.Text);
			//} catch ( Exception err ) {
			//    MessageBox.Show(err.Message, "Error processing XPath query:");
			//    return;
			//}

			//DlgXPathResult dlg = new DlgXPathResult(nodeList, edNewRowOn.Text);
			//dlg.ShowDialog(this);
		}
		#endregion
		#endregion

		#region Schema Validation Handler
		// report any errors to the schema error edit box
		private void SchemaValidationHandler(object sender, ValidationEventArgs args)
		{
			MessageBox.Show(args.Message, "Schema compilation error:");
		}
		#endregion

		private void TrueFalseToBool(object sender, ConvertEventArgs args)
		{
			if ( args.Value.GetType() == typeof(System.DBNull) ) {
				args.Value = false;
			}
		}

		private void dgv_DataError(object sender, DataGridViewDataErrorEventArgs e)
		{
			MessageBox.Show(e.Exception.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
		}
		private void tag_TableNewRow(object sender, DataTableNewRowEventArgs e)
		{
			DataTable dt = sender as DataTable;

			TableInfo ti = tableInfo[dt] as TableInfo;

			// Set the child relationship ID's to the parent!
			// There will be only one parent relationship except
			// for the root table.
			try {
				if ( dt.ParentRelations.Count != 0 ) {
					DataRelation parentRelation = dt.ParentRelations[0];
					DataTable dt2 = parentRelation.ParentTable;
					int n = BindingContext[dt2].Position;

					// this is always a 1:1 relationship
					DataColumn dcParent = parentRelation.ParentColumns[0];
					DataColumn dcChild = parentRelation.ChildColumns[0];
					string val = dt2.Rows[n][dcParent].ToString();
					e.Row[dcChild] = val;

				}
			} catch { }
		}

		#region Navigation Bar Event Handlers

		// Create a new record in the associated table.
		// This function also creates new records in all child tables and
		// sets the child-parent relationship key in the child tables.
		private void NewRecord(object sender, EventArgs e)
		{
			try {
				DataTable dt = null;
				if ( sender is Button ) {
					Button btn = sender as Button;
					//DataTable dt = btn.Tag as DataTable;
					dt = btn.Tag as DataTable;
				} else
					dt = sender as DataTable;
				
				if ( dt == null )
					return;

				dt.Rows.Add(dt.NewRow());
				int newRow = dt.Rows.Count - 1;
				BindingContext[dt].Position = newRow;

				TableInfo ti = tableInfo[dt] as TableInfo;


				// Set the child relationship ID's to the parent!
				// There will be only one parent relationship except
				// for the root table.

				if ( dt.ParentRelations.Count != 0 ) {
					DataRelation parentRelation = dt.ParentRelations[0];
					DataTable dt2 = parentRelation.ParentTable;
					int n = BindingContext[dt2].Position;

					// this is always a 1:1 relationship
					DataColumn dcParent = parentRelation.ParentColumns[0];
					DataColumn dcChild = parentRelation.ChildColumns[0];

					string val = dt2.Rows[n][dcParent].ToString();
					dt.Rows[newRow][dcChild] = val;

					n = GetMatchingRows(dt);
					ti.pos = n;
					ti.rows = n;
				} else {
					ti.pos = newRow + 1;
					ti.rows = newRow + 1;
				}


				UpdateRecordCountInfo(dt);

				// for each child, also create a new row in the child's table
				foreach ( DataRelation childRelation in dt.ChildRelations ) {
					DataTable dtChild = childRelation.ChildTable;
					NewRecord(dt, dtChild, childRelation);
				}
			} catch { }
		}

		private void NewRecord(DataTable parent, DataTable child, DataRelation dr)
		{
			// add the child record
			child.Rows.Add(child.NewRow());

			// get the last row of the parent (this is the new row)
			// and the new row in the child (also the last row)
			int newParentRow = parent.Rows.Count - 1;
			int newChildRow = child.Rows.Count - 1;

			// go to this record
			BindingContext[child].Position = newChildRow;

			// get the parent and child columns
			// copy the parent ID (auto sequencing) to the child to establish
			// the relationship.  This is always a 1:1 relationship
			DataColumn dcParent = dr.ParentColumns[0];
			DataColumn dcChild = dr.ChildColumns[0];
			string val = parent.Rows[newParentRow][dcParent].ToString();
			child.Rows[newChildRow][dcChild] = val;

			( (TableInfo)tableInfo[child] ).pos = 1;
			( (TableInfo)tableInfo[child] ).rows = 1;
			UpdateRecordCountInfo(child);

			// recurse into children of this child
			foreach ( DataRelation childRelation in child.ChildRelations ) {
				DataTable dt2 = childRelation.ChildTable;
				NewRecord(child, dt2, childRelation);
			}
		}

		private void FirstRecord(object sender, EventArgs e)
		{
			Button btn = sender as Button;
			DataTable dt = btn.Tag as DataTable;
			TableInfo ti = tableInfo[dt] as TableInfo;
			ti.pos = 1;
			FirstRecord(dt, ti);
			UpdateRecordCountInfo(dt);
		}

		private void PrevRecord(object sender, EventArgs e)
		{
			Button btn = sender as Button;
			DataTable dt = btn.Tag as DataTable;
			TableInfo ti = tableInfo[dt] as TableInfo;
			if ( ti.pos > 1 ) {
				( (TableInfo)tableInfo[dt] ).pos--;
				PrevRecord(dt, ti);
				UpdateRecordCountInfo(dt);
			}
		}

		private void NextRecord(object sender, EventArgs e)
		{
			Button btn = sender as Button;
			DataTable dt = btn.Tag as DataTable;
			TableInfo ti = tableInfo[dt] as TableInfo;
			if ( ti.pos < ti.rows ) {
				( (TableInfo)tableInfo[dt] ).pos++;
				NextRecord(dt, ti);
				UpdateRecordCountInfo(dt);
			}
		}

		private void LastRecord(object sender, EventArgs e)
		{
			Button btn = sender as Button;
			DataTable dt = btn.Tag as DataTable;
			int n = dt.Rows.Count;
			TableInfo ti = tableInfo[dt] as TableInfo;
			ti.pos = ti.rows;
			LastRecord(dt, ti);
			UpdateRecordCountInfo(dt);
		}

		private void DeleteRecord(object sender, EventArgs e)
		{
			Button btn = sender as Button;
			DataTable dt = btn.Tag as DataTable;
			int n = BindingContext[dt].Position;
			//dt.Rows.RemoveAt(n);//original
			//t
			if ( n > -1 )
				dt.Rows.RemoveAt(n);
			else
				return;
			//et

			// if a child table...
			if ( dt.ParentRelations.Count != 0 ) {
				// ...get all rows matching the parent ID
				n = GetMatchingRows(dt);
			} else {
				// ...otherwise get all rows of the root table
				n = dt.Rows.Count;
			}
			TableInfo ti = tableInfo[dt] as TableInfo;
			ti.rows = n;

			// if position is now past # of rows...
			if ( ti.pos > ti.rows ) {
				// set position to last row
				ti.pos = ti.rows;
			}

			// update the display
			UpdateRecordCountInfo(dt);

			if ( n != 0 )		// table has records?
			{

				// set to the next available row
				if ( dt.ParentRelations.Count != 0 ) {
					SetPositionToRow(dt, ti.dataRows[ti.pos - 1]);
				} else {
					BindingContext[dt].Position = ti.pos - 1;
				}
			}

			// reset all children to record #1
			ResetAllChildren(dt);

			// Cascading delete automatically implemented
			// by the table constraints.
		}

		private void FirstRecord(DataTable dt, TableInfo ti)
		{
			try {
				if ( dt.ParentRelations.Count == 0 ) {
					BindingContext[dt].Position = 0;
				} else {
					// get the first row in the record set that matches the parent
					SetPositionToRow(dt, ti.dataRows[ti.pos - 1]);
				}
				ResetAllChildren(dt);
			} catch { }
		}

		private void PrevRecord(DataTable dt, TableInfo ti)
		{
			if ( dt.ParentRelations.Count == 0 ) {
				BindingContext[dt].Position--;
			} else {
				// get the previous row that matches the parent ID
				SetPositionToRow(dt, ti.dataRows[ti.pos - 1]);
			}
			ResetAllChildren(dt);
		}

		private void NextRecord(DataTable dt, TableInfo ti)
		{
			if ( dt.ParentRelations.Count == 0 ) {
				BindingContext[dt].Position++;
			} else {
				// get the next row that matches the parent ID
				SetPositionToRow(dt, ti.dataRows[ti.pos - 1]);

			}
			ResetAllChildren(dt);
		}

		private void LastRecord(DataTable dt, TableInfo ti)
		{
			try {
				if ( dt.ParentRelations.Count == 0 ) {
					BindingContext[dt].Position = dt.Rows.Count - 1;
				} else {
					// get the last row that matches the parent ID
					SetPositionToRow(dt, ti.dataRows[ti.pos - 1]);
				}
				ResetAllChildren(dt);
			} catch { }
		}

		private void ResetAllChildren(DataTable dt)
		{
			// update all children of the table to match our new ID
			foreach ( DataRelation dr in dt.ChildRelations ) {
				DataTable dtChild = dr.ChildTable;
				ResetChildRecords(dtChild);
			}
		}

		private void ResetChildRecords(DataTable dt)
		{
			int n = GetMatchingRows(dt);
			TableInfo ti = tableInfo[dt] as TableInfo;
			//t
			if ( n == 0 )
				ti.pos = n;
			else
				ti.pos = 1;
			//et

			//ti.pos=1;//original
			ti.rows = n;
			UpdateRecordCountInfo(dt);
			if ( n != 0 ) {
				SetPositionToRow(dt, ti.dataRows[0]);
			}
			foreach ( DataRelation dr in dt.ChildRelations ) {
				DataTable dtChild = dr.ChildTable;
				ResetChildRecords(dtChild);
			}
		}

		private void SetPositionToRow(DataTable dt, DataRow row)
		{
			for ( int i = 0; i < dt.Rows.Count; i++ ) {
				if ( dt.Rows[i] == row ) {
					BindingContext[dt].Position = i;
					break;
				}
			}
		}

		#endregion

		private void edXPath_TextChanged(object sender, EventArgs e)
		{

		}

		private void menuItem3_Click(object sender, EventArgs e)
		{
			MessageBox.Show(this.XML);
		}

		private void toolStripMenuItem1_Click(object sender, EventArgs e)
		{
			ToolStripDropDownItem i = sender as ToolStripDropDownItem;
			ContextMenuStrip strip = ( i.Owner ) as ContextMenuStrip;
			//MessageBox.Show((strip.SourceControl.Tag as string[])[1]);

			FormStyle.ItemRow row = null;
			//FormStyle.ItemRow r9 = null;

			DataRow[] rows = _formStyle.Item.Select("FQN = '" + ( strip.SourceControl.Tag as string[] )[1] + "'");
			if ( rows != null && rows.Length > 0 ) {
				row = ( (FormStyle.ItemRow)rows[0] );
			} else
				row = CreateItemRow(strip.SourceControl as GroupBox);

			FormEdit fe = new FormEdit(_xmlschema, row);
			DialogResult res = fe.ShowDialog();
			if ( res == DialogResult.OK ) {
				//r9 = fe.Row;
				row = fe.Row;
				this.Controls.Clear();
				doc.DataSet.AcceptChanges();
				_formStyle.AcceptChanges();
				ConstructGUI(doc.DataSet);
				UpdateTableInfo();

			}
			//MessageBox.Show(this.FormDefinitionXML);

		}

		#endregion

		#endregion

		#region Class: TypeInfo
		public class TypeInfo
		{
			public TypeInfo() {typeName="";}
			public TypeInfo(string typeName)
			{
				this.typeName=typeName;
				length="-1";
				minLength="-1";
				maxLength="-1";
				pattern="";
				maxInclusive=null;
				maxExclusive=null;
				minInclusive=null;
				minExclusive=null;
				fractionDigits="-1";
				totalDigits="-1";
				whiteSpace="";
				enumeration=new ArrayList();
			}

			public string typeName;

			// facet information
			public string length;
			public string minLength;
			public string maxLength;
			public string pattern;
			public string maxInclusive;
			public string maxExclusive;
			public string minInclusive;
			public string minExclusive;
			public string fractionDigits;
			public string totalDigits;
			public string whiteSpace;			// "preserve", "replace", or "collapse"
			public ArrayList enumeration;
		}
		#endregion

		#region Class: TableInfo
		public class TableInfo
		{
			public TableInfo()
			{
				tb=null;
				rows=0;
				pos=0;
			}

			public TextBox tb;
			public int rows;
			public int pos;
			public DataRow[] dataRows;
		}
		#endregion

	}
}
